package com.atguigu.gmall.product.service.impl;
import com.atguigu.gmall.product.biz.CategoryBizSerivce;
import com.atguigu.gmall.product.entity.*;
import com.atguigu.gmall.feign.search.SearchFeignClient;
import com.atguigu.gmall.product.mapper.BaseTrademarkMapper;
import com.atguigu.gmall.search.entity.SearchAttr;

import java.util.Date;

import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.product.service.SkuAttrValueService;
import com.atguigu.gmall.product.service.SkuImageService;
import com.atguigu.gmall.product.service.SkuSaleAttrValueService;
import com.atguigu.gmall.product.vo.SkuInfoSaveVo;
import com.atguigu.gmall.product.vo.SkuInfoUpdateVo;
import com.atguigu.gmall.search.entity.Goods;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.gmall.product.service.SkuInfoService;
import com.atguigu.gmall.product.mapper.SkuInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author DaiLie
 * @description 针对表【sku_info(库存单元表)】的数据库操作Service实现
 * @createDate 2024-08-30 16:27:48
 */
@Slf4j
@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo>
        implements SkuInfoService{

    @Autowired
    SkuInfoMapper skuInfoMapper;

    @Autowired
    SkuImageService skuImageService;

    @Autowired
    SkuAttrValueService skuAttrValueService;

    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    StringRedisTemplate redisTemplate;

    ScheduledExecutorService pool = Executors.newScheduledThreadPool(4);

    @Autowired
    RedissonClient redisson;

    @PostConstruct
    public void initSkuIdBloom(){
        // 初始化布隆
        RBloomFilter<Object> filter = redisson.getBloomFilter(RedisConst.BLOOM_SKUID);
        if (!filter.isExists()){
            log.info("布隆过滤器尚未初始化，正在初始化....");
            filter.tryInit(1000000,0.0000001);
            List<Long> allSkuId = getAllSkuId();
            allSkuId.stream().forEach(item->{
                filter.add(item);
            });
            log.info("布隆过滤器初始化完成....");
        }
    }


    @Transactional
    @Override
    public void saveSkuInfo(SkuInfoSaveVo vo) {
        // TODO 保存SKU

        SkuInfo skuInfo = new SkuInfo();
        BeanUtils.copyProperties(vo,skuInfo);

        skuInfoMapper.insert(skuInfo);

        Long skuId = skuInfo.getId();

        // 保存sku_images
        List<SkuImage> images = vo.getSkuImageList().stream()
                .map(item -> {
                    SkuImage image = new SkuImage();
                    BeanUtils.copyProperties(item, image);
                    image.setSkuId(skuId);
                    return image;
                }).collect(Collectors.toList());

        skuImageService.saveBatch(images);

        // 保存 sku 平台属性名和值
        List<SkuAttrValue> attrValues = vo.getSkuAttrValueList().stream()
                .map(item -> {
                    SkuAttrValue skuAttrValue = new SkuAttrValue();
                    BeanUtils.copyProperties(item, skuAttrValue);
                    // 回填 sku_id
                    skuAttrValue.setSkuId(skuId);
                    return skuAttrValue;
                }).collect(Collectors.toList());
        skuAttrValueService.saveBatch(attrValues);

        // 保存 sku 销售属性名和值
        List<SkuSaleAttrValue> saleAttrValues = vo.getSkuSaleAttrValueList().stream()
                .map(item -> {
                    SkuSaleAttrValue value = new SkuSaleAttrValue();
                    BeanUtils.copyProperties(item, value);
                    value.setSkuId(skuId);
                    value.setSkuId(skuInfo.getSpuId());
                    return value;
                }).collect(Collectors.toList());
        skuSaleAttrValueService.saveBatch(saleAttrValues);

        // 吧商品信息添加到布隆过滤器
        RBloomFilter<Object> filter = redisson.getBloomFilter(RedisConst.BLOOM_SKUID);
        filter.add(skuId);

        log.info("sku信息保存成功：skuId={}",skuId);
    }

    @Override
    public void changeOnSale(Long skuId, int status) {
        // 修改数据库状态
        skuInfoMapper.updateSaleStatus(skuId,status);
        // TODO 上架的商品代表可以被检索到

    }

    @Override
    public BigDecimal getSkuPrice(Long skuId) {

        BigDecimal price = skuInfoMapper.getSkuPrice(skuId);
        return price;
    }

    @Override
    public List<Long> getAllSkuId() {
        return skuInfoMapper.getAllSkuId();
    }

    @Override
    public void updateSkuInfo(SkuInfoUpdateVo vo) {
        // 去数据库修改

        // 延迟双删
        redisTemplate.delete(RedisConst.SKU_DETAIL_CACHE_PREFIX + vo.getId());

        // 提交延迟任务。有oom风险
        pool.schedule(()->{
            redisTemplate.delete(RedisConst.SKU_DETAIL_CACHE_PREFIX + vo.getId());
        },10, TimeUnit.SECONDS);


        // 立即结束

    }

    @Autowired
    SearchFeignClient searchFeignClient;

    @Override
    public void onSale(Long skuId) {
        // 修改状态
        this.changeOnSale(skuId,1);
        // 把sku保存到es中  http://sph.atguigu.cn/
        Goods goods = prepareGoods(skuId);
        // 远程调用ES服务进行保存
        searchFeignClient.onSaleGoods(goods);
    }

    @Autowired
    BaseTrademarkMapper baseTrademarkMapper;
    @Autowired
    CategoryBizSerivce categoryBizSerivce;

    @Autowired
    ThreadPoolExecutor executor;
    // 生成某个商品在es中进行存储的数据模型
    private Goods prepareGoods(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);

        // 查询商品sku的基本信息
        Goods goods = new Goods();
        CompletableFuture<Void> skuInfoFuture = CompletableFuture.runAsync(() -> {
            goods.setId(skuId);
            goods.setDefaultImg(skuInfo.getSkuDefaultImg());
            goods.setTitle(skuInfo.getSkuName());
            goods.setPrice(skuInfo.getPrice());
            goods.setCreateTime(new Date());
        }, executor);

        // 查询品牌
        CompletableFuture<Void> tradeMarkFuture = CompletableFuture.runAsync(() -> {
            BaseTrademark trademark = baseTrademarkMapper.selectById(skuInfo.getTmId());
            goods.setTmId(skuInfo.getTmId());
            goods.setTmName(trademark.getTmName());
            goods.setTmLogoUrl(trademark.getLogoUrl());
        }, executor);

        // 查询分类
        CompletableFuture<Void> categoryFuture = CompletableFuture.runAsync(() -> {
            Long c3Id = skuInfo.getCategory3Id();
            CategroyViewEntity view = categoryBizSerivce.getCategoryView(c3Id);
            goods.setCategory1Id(view.getC1id());
            goods.setCategory1Name(view.getC1name());
            goods.setCategory2Id(view.getC2id());
            goods.setCategory2Name(view.getC2name());
            goods.setCategory3Id(view.getC3id());
            goods.setCategory3Name(view.getC3name());
        }, executor);

        // 热度分
        goods.setHotScore(0L);

        // 查询某个商品的所有平台属性，名和值
        CompletableFuture<Void> attrFuture = CompletableFuture.runAsync(() -> {
            List<SearchAttr> searchAttrs = skuAttrValueService.getSkuAttrAndValue(skuId);
            goods.setAttrs(searchAttrs);
        }, executor);

        CompletableFuture.allOf(skuInfoFuture,
                tradeMarkFuture,categoryFuture,attrFuture).join();

        return goods;
    }

    @Override
    public void cancelSale(Long skuId) {
        this.changeOnSale(skuId,0);

        //删除es中这个商品
        searchFeignClient.cancelSale(skuId);
    }
}




